package code.example.javassist.test;

import javassist.*;

import java.lang.reflect.Method;

public class CreateAClass {

    private void addField( CtClass ctClass) throws Exception {
        CtField ctField =  CtField.make("private java.lang.String name;",ctClass);
        ctClass.addField(ctField);
         ctField =  CtField.make("private java.lang.Integer age;",ctClass);
        ctClass.addField(ctField);

    }
    private void addConstructor(CtClass ctClass) throws Exception {
        CtConstructor ctConstructor = new CtConstructor(new CtClass[]{}, ctClass);
        ctConstructor.setBody("{" +
                "this.name = \"a\";" +
                "this.age = new java.lang.Integer(10);" +
                "}");
        ctClass.addConstructor(ctConstructor);
    }

    private void addMethod(CtClass ctClass) throws Exception {
        CtMethod ctMethod =  CtNewMethod.make("" +
                "public void printMessage(){" +
                "   java.lang.System.out.println(\"this.name=\"+this.name+\",this.age=\"+this.age);"+
                "}",ctClass);
        ctClass.addMethod(ctMethod);
    }
    private void addMethod1(CtClass ctClass) throws Exception {
        ClassPool classPool = ClassPool.getDefault();
        CtClass sringCtClass = classPool.getCtClass("java.lang.String");
        CtMethod ctMethod =  CtNewMethod.make(CtClass.voidType,"toPrint",new CtClass[]{sringCtClass},null,"{}",ctClass);
        ctClass.addMethod(ctMethod);
        ctMethod.setBody("{" +
                "this.printMessage();" +
                "java.lang.System.out.println(\" method execute finish \");" +
                "}");

    }
    private void addMethod2(CtClass ctClass) throws Exception {
        CtMethod ctMethod =  CtNewMethod.make("" +
                "public void printX(){" +
                "   printMessage();"+
                "}",ctClass);
        ctClass.addMethod(ctMethod);
    }

    private void callMethod(Class classz) throws Exception {
        //Method method = classz.getMethod("printMessage",null);
        //method.invoke(classz.newInstance(),null);
        Method  method = classz.getMethod("toPrint",new Class[]{String.class});
        method.invoke(classz.newInstance(),new Object []{"ok"});

          method = classz.getMethod("printX",null);
        method.invoke(classz.newInstance(),null);


    }
    public void create(){
        try {
            ClassPool classPool = ClassPool.getDefault();
            CtClass ctClass = classPool.makeClass("code.example.javassist.test.CreateClass");
            addField(ctClass);
            addConstructor(ctClass);
            addMethod(ctClass);
            addMethod1(ctClass);
            addMethod2(ctClass);
            Class classz = ctClass.toClass();
            callMethod(classz);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public static void main(String args []){
        new CreateAClass().create();
    }
}
